# This is the profiler for table/s and database/s.
# This can be used to gather statistics such as number of columns, number of records, primary key.
# This can be used before ETL operations so that user can get the structural overview of the table.

class Profile

      class Rule

          def self.method_missing(method_name)
              puts method_name  
              method_name_array = method_name.to_s.split("_")
              $column_number = method_name_array[2..3].join("_")
              $table_name = method_name_array[6..(method_name_array.length-1)].join("_")
              return Profile::Rule.new
          end

            
          def self.profile_single_column(column_name,table_name,connection)    
              col_struc = connection.execute("desc #{table_name}")
              col_struc.each do |col|
                    column_one = first_letter_capital(col[0])
                    column_two = first_letter_capital(column_name)
                    if col[0] == column_name || col[0].upcase == column_name || col[0].downcase == column_name || column_one == column_two
                        generate_column_profile(col,table_name,connection)
                    end	
              end          
          end


          def under connection
              all_columns = connection.execute("desc #{$table_name}")
              req_columns = get_columns_from_positions($column_number,all_columns)
              for column in req_columns
                  generate_column_profile(column,$table_name,connection)
              end
          end             
    
      end  
      
      
      # Dependency check for multiple tables.
      def self.check_primary_key_dependency(options={})
            options.each{|key,value|
            table_names_array = []
            key = [key] if !key.respond_to?"join"
            for connection in key
                all_tables = connection.execute("show tables")
                all_tables.each{|table_name|
                    table_names_array = table_names_array + table_name
                }
                column_list = (get_required_columns(table_names_array,value,"",connection)).uniq
                column_list.each{|table_name|
                    Profile.generate_primary_key_dep_profile(table_name,connection)
                }
            end    
        }
      end  

            
      def self.check_dependency(options={})
            options.each{|key,value|
                key = [key] if !key.respond_to?"join"
                for connection in key
                    table_names_array = []
                    all_tables = connection.execute("show tables")
                    all_tables.each{|table_name|
                        table_names_array = table_names_array + table_name
                    }
                    inner_hash = value
                    inner_hash.each{|inner_key,inner_value|
                        tables_array = inner_key
                        table_names = (get_required_columns(table_names_array,tables_array,"",connection)).uniq
                        table_names.each{|single_table|
                              all_columns = get_column_list(connection,single_table)
                              parent_columns = get_required_columns(all_columns,inner_value[0],"",connection)
                              child_columns = get_required_columns(all_columns,inner_value[1],"",connection)
                              ActiveProfiler.generate_dependency_profile(parent_columns,child_columns,connection,single_table)
                        }    
                    }
                end    
            }
      end  



      def self.generate_primary_key_dep_profile(table_name,connection)
          primary_key = get_primary_key(table_name,connection)
          if !primary_key.nil?
                all_columns = get_column_list(connection,table_name)  
                dep_pro = ActiveProfiler.generate_dependency_profile([primary_key],all_columns,connection,table_name)
                if dep_pro == 0
                      puts "#{table_name} is having all non-key attributes dependent on primary key."
                end  
          else
                puts "#{table_name} does not have any attribute set as primary key you defined."
          end      
      end
      
      
      
      # This is the method missing for dynamic profiling of the tables 
      def self.method_missing(method_name)
            method_array = method_name.to_s.split("_")
            $table_name = method_array[(method_array.index("is")+1)..(method_array.length-1)].join("_")  
            return Profile.new
      end  



      # This is the method for passing connection argument for the table profiling.
      # This works in collaboration with other methods.
      def under(connection)
          all_columns = connection.execute("desc #{$table_name}")
          all_columns.each{|single_column|
              generate_column_profile(single_column,$table_name,connection)
          }
      end
  


      # This is when you want to profile entire database to which connection has been made.
      def self.connection_is(connection)
          all_tables = connection.tables
          for table in all_tables
              $table_name = table
              Profile.new.under(connection)
          end
      end  
   
   
   
      # This is for generating profiles of tables under different databases.
      def self.generate_profile_for_tables(options={})
          options.each{|key,value|
            key = [key] if !key.respond_to?"join"
            for connection in key 
                table_list = Extraction.get_all_table_list(connection)
                required_tables = get_required_columns(table_list,value,"",connection)
                required_tables.each{|table_name|
                      $table_name = table_name
                      Profile.new.under(connection)
                }
            end
          }    
      end
   
   
      # This is for profiling multiple databases.
      def Profile.generate_profile_for_databases(conn_array)
          for conn in conn_array
              Profile.connection_is(conn)
          end  
      end

end  